/**
 * Copyright (C) 2013 DaiKit.com - daikit4gxt module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/daikit4gxt
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.daikit4gxt.client.editor;

import com.daikit.commons.shared.bean.AbstractDkModifiableBeanWithId;
import com.daikit.commons.shared.utils.DkStringUtils;
import com.sencha.gxt.core.client.ValueProvider;
import com.sencha.gxt.data.shared.Store.Change;
import com.sencha.gxt.data.shared.Store.Record;
import com.sencha.gxt.data.shared.TreeStore;
import com.sencha.gxt.data.shared.TreeStore.TreeNode;


/**
 * Utility to visit a TreeStoreEditor to have all its associated list of beans dirty status and paths updated according
 * to records.
 * 
 * @author rdupuis
 * @author tcaselli
 * @version $Revision$ Last modifier: $Author$ Last commit: $Date$
 */
public class TreeStorePreFlushUtil
{

	/**
	 * Visit a TreeStoreEditor to have all its associated list of beans dirty status and paths updated according to
	 * records.
	 * 
	 * @param editor
	 *           the {@link TreeStoreEditor}
	 */
	@SuppressWarnings("rawtypes")
	public static <T extends TreeNode<T>> void visit(final TreeStoreEditor<T> editor)
	{
		for (final Record record : editor.getStore().getModifiedRecords())
		{
			if (!record.getChanges().isEmpty())
			{
				final Object model = record.getModel();
				if (model instanceof AbstractDkModifiableBeanWithId)
				{
					final AbstractDkModifiableBeanWithId modifiableBean = (AbstractDkModifiableBeanWithId) model;
					dirtyBeanAndAncestors(editor.getStore(), modifiableBean);
					for (final Object changeObject : record.getChanges())
					{
						final Change change = (Change) changeObject;
						final String path = ((ValueProvider) change.getChangeTag()).getPath();
						if (DkStringUtils.hasText(path))
						{
							modifiableBean.getDirtyPaths().add(path.indexOf(".") == -1 ? path : path.substring(0, path.indexOf(".")));
						}
					}
				}
			}
		}
	}

	@SuppressWarnings(
	{ "rawtypes", "unchecked" })
	private static <M extends AbstractDkModifiableBeanWithId> void dirtyBeanAndAncestors(final TreeStore store,
			final AbstractDkModifiableBeanWithId bean)
	{
		AbstractDkModifiableBeanWithId current = bean;
		int i = 0;
		while (current != null)
		{
			current.setDirty(true);
			if (i > 0)
			{
				current.getDirtyPaths().add("children");
			}
			current = (AbstractDkModifiableBeanWithId) store.getParent(current);
			i++;
		}
	}
}
